#pragma once
#include "util.hpp"
namespace qbe::editing::Extension {

double distance(qlib::Vec2d a, qlib::Vec2d b) {
  return std::sqrt(std::pow(a.x - b.x, 2) + std::pow(a.y - b.y, 2));
}

qlib::Vec2d normalizeVector(qlib::Vec2d pt) {
  float length = sqrt(pt.x * pt.x + pt.y * pt.y);
  pt = pt / length;
  return pt;
}

qlib::Vec2d transOutPoint(qlib::Vec2d& p, LayerRef::LayerModel& levelParam) {
  // osg::Vec4d p_m = osg::Vec4d(p.x, p.y, 0.f, 1.f) * LayoutCtrlData::getEditLowerLayerMatrixd(); //矩阵变换
  return qlib::Vec2d(p.x, p.y);
}

bool rayIntersectsAABB2D(qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, qlib::Vec2d& min, qlib::Vec2d& max) {
  if (min.x > max.x && min.y > max.y)
    return false;  //不合法包围盒
  float tminX = (min.x - ray_start.x) / ray_dir.x;
  float tmaxX = (max.x - ray_start.x) / ray_dir.x;
  float tminY = (min.y - ray_start.y) / ray_dir.y;
  float tmaxY = (max.y - ray_start.y) / ray_dir.y;

  float tenter = std::max(std::min(tminX, tmaxX), std::min(tminY, tmaxY));
  float texit = std::min(std::max(tminX, tmaxX), std::max(tminY, tmaxY));

  return tenter <= texit && texit > 0;
}

// 求两个向量的叉积
double cross_product(const qlib::Vec2d& p1, const qlib::Vec2d& p2) {
  return p1.x * p2.y - p1.y * p2.x;
}

// 计算两条线段的交点
bool computeIntersection(const qlib::Vec2d& A, const qlib::Vec2d& B, const qlib::Vec2d& C, const qlib::Vec2d& D, qlib::Vec2d& intersection) {
  qlib::Vec2d AB = {B.x - A.x, B.y - A.y};
  qlib::Vec2d CD = {D.x - C.x, D.y - C.y};
  qlib::Vec2d AC = {C.x - A.x, C.y - A.y};

  double denominator = cross_product(AB, CD);

  // 如果 denominator 接近于 0，线段平行或重叠
  if (std::abs(denominator) < 1e-9) {
    return false;
  }

  // 计算参数 t 和 s
  double t = cross_product(AC, CD) / denominator;
  double s = cross_product(AC, AB) / denominator;

  // 检查 t 和 s 是否在 [0, 1] 范围内
  if (t >= 0 && t <= 1 && s >= 0 && s <= 1) {
    // 计算交点坐标
    intersection.x = A.x + t * AB.x;
    intersection.y = A.y + t * AB.y;
    return true;
  }

  //判断两个端点
  if (distancePointToSegment(C, A, B) < 1e-4) {
    intersection.x = C.x;
    intersection.y = C.y;
    return true;
  }

  if (distancePointToSegment(D, A, B) < 1e-4) {
    intersection.x = D.x;
    intersection.y = D.y;
    return true;
  }

  return false;
}

std::vector<entt::entity> getQueryEntities(std::vector<qbe::layout::CellQuad::Node>& nodes) {
  std::vector<entt::entity> entities;
  for (auto node : nodes) {
    entities.push_back(node.entity);
  }
  return entities;
}

std::vector<ExtendLine> getPreExtendNodes(layout::LayoutCmd& layout_cmd, qlib::Cell::s_ptr current_cell, qlib::Vec2d mouse_pos,
                                          PartCheckedInfo& pre_extend_line, qlib::Path::s_ptr mouse_line, LayerRef::LayerModel& levelparam) {
  std::vector<std::vector<int>> indexes;
  std::vector<qlib::Vec2d> hit_points;
  std::vector<ExtendLine> res;
  auto& reg = current_cell->reg;
  //多选
  if (mouse_line && !mouse_line->spine.points.empty()) {
    qlib::Vec2d start = mouse_line->spine.points[0];
    qlib::Vec2d end = mouse_line->spine.points[1];
    std::vector<qlib::Vec2d> box = mouse_line->bounding_box();
    if (levelparam.editing_ref_cell) {
      //将多选线坐标转换到上层计算顶层包围盒
      qlib::Vec2d start_m = transOutPoint(start, levelparam);
      qlib::Vec2d end_m = transOutPoint(end, levelparam);
      box[0].x = std::min(start_m.x, end_m.x);
      box[0].y = std::min(start_m.y, end_m.y);
      box[1].x = std::max(start_m.x, end_m.x);
      box[1].y = std::max(start_m.y, end_m.y);
    }
    box[0].x -= 0.1;
    box[0].x -= 0.1;
    box[1].y += 0.1;
    box[1].y += 0.1;
    std::vector<entt::entity>& nodes = getQueryEntities(layout_cmd.query_quad(
        box[0].x, box[0].y, box[1].x - box[0].x,
        box[1].y - box[0].y));  // = LayoutCtrlData::getElementsByBox(box[0].x, box[0].y, box[1].x - box[0].x, box[1].y - box[0].y); //选择对象
    qlib::Vec2d ray_start = start;
    qlib::Vec2d ray_dir = end - start;
    if (!nodes.empty()) {
      int a = 0;
      for (auto entt : nodes) {
        // if (node->getEleLock())
        //   continue;
        auto line = reg.try_get<qlib::Path::s_ptr>(entt);
        if (line && (*line)->getLineWidth() == 0) {
          std::vector<qlib::Vec2d> m_obb = (*line)->bounding_box();
          qlib::Vec2d min(m_obb[0].x, m_obb[0].y);
          qlib::Vec2d max(m_obb[1].x, m_obb[1].y);
          if (!rayIntersectsAABB2D(ray_start, ray_dir, min, max))
            continue;
          bool need_extend = false;
          std::vector<qlib::Vec2d>& points = (*line)->spine.points;
          int max_size = points.size() - 1;
          for (size_t i = 0; i < max_size; ++i) {
            qlib::Vec2d intersection;  //交点
            int s = i;
            int e = i + 1;
            if (computeIntersection(start, end, points[s], points[e], intersection)) {
              std::vector<int> idx;
              idx.push_back(s);
              idx.push_back(e);
              indexes.push_back(idx);
              hit_points.push_back(intersection);
              need_extend = true;
            }
          }
          if (need_extend) {
            res.push_back(ExtendLine(entt, (*line), indexes, hit_points));
          }
          indexes.clear();
          hit_points.clear();
        }
      }
    }
  } else {
    //单选
    bool is_lock = false;
    auto line = reg.try_get<qlib::Path::s_ptr>(pre_extend_line.node);
    if (line && (*line)->getLineWidth() == 0 && pre_extend_line.indexs.size() == 2 && !is_lock) {
      // indexes.push_back(preCheckedLine.indexs);
      hit_points.push_back(mouse_pos);
      res.push_back(ExtendLine(pre_extend_line.node, (*line), {pre_extend_line.indexs}, hit_points));
    }
  }
  return res;
}

qlib::Vec2d findNearestVertex(const std::vector<qlib::Vec2d>& vertices, const qlib::Vec2d& target, bool& finded) {
  qlib::Vec2d nearest_vertex;
  double min_distance = std::numeric_limits<double>::max();
  // Iterate through the rest of the vertices
  double threshold = 0.0001;
  for (size_t i = 0; i < vertices.size(); ++i) {
    double dist = distance(vertices[i], target);
    if (dist < min_distance && dist >= threshold) {
      min_distance = dist;
      nearest_vertex = vertices[i];
      finded = true;
    }
  }
  return nearest_vertex;
}

bool pointIsInsideScreen(qlib::Vec2d& point, LayerRef::LayerModel& levelParam, std::vector<double> screen_box) {
  if (levelParam.editing_ref_cell) {
    qlib::Vec2d& point_m = transOutPoint(point, levelParam);
    return point_m.x >= screen_box[0] && point_m.x <= screen_box[2] && point_m.y >= screen_box[1] && point_m.y <= screen_box[3];
  } else {
    return point.x >= screen_box[0] && point.x <= screen_box[2] && point.y >= screen_box[1] && point.y <= screen_box[3];
  }
}

void computeRayBoundingBox(qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, qlib::Vec2d& min, qlib::Vec2d& max, std::vector<double> screen_box) {
  // Choose a large enough value to extend the ray
  double L = std::numeric_limits<double>::max();

  // Calculate the endpoint of the ray
  double x1 = ray_start.x + L * ray_dir.x;
  double y1 = ray_start.y + L * ray_dir.y;
  // Determine bounding box
  double xmin = std::max(std::min(ray_start.x, x1), screen_box[0]);
  double xmax = std::min(std::max(ray_start.x, x1), screen_box[2]);
  double ymin = std::max(std::min(ray_start.y, y1), screen_box[1]);
  double ymax = std::min(std::max(ray_start.y, y1), screen_box[3]);
  min.x = xmin;
  min.y = ymin;
  max.x = xmax;
  max.y = ymax;
}

double getRayToLineSegmentDist(qlib::Vec2d& rayOrigin, qlib::Vec2d& rayDirection, qlib::Vec2d& point1, qlib::Vec2d& point2) {
  double xmin = std::min(point1.x, point2.x);
  double xmax = std::max(point1.x, point2.x);
  double ymin = std::min(point1.y, point2.y);
  double ymax = std::max(point1.y, point2.y);
  if (!rayIntersectsAABB2D(rayOrigin, rayDirection, qlib::Vec2d(xmin, ymin), qlib::Vec2d(xmax, ymax)))
    return -1.0f;

  qlib::Vec2d v1 = rayOrigin - point1;
  qlib::Vec2d v2 = point2 - point1;
  qlib::Vec2d v3 = qlib::Vec2d(-rayDirection.y, rayDirection.x);

  float dot = v2.x * v3.x + v2.y * v3.y;  //v2.dot(v3);
  if (abs(dot) < 0.000001)
    return -1.0f;

  float t1 = (v2.x * v1.y - v2.y * v1.x) / dot;  //v2.cross(v1) / dot
  float t2 = (v1.x * v3.x + v1.y * v3.y) / dot;

  if (t1 >= 0.001 && (t2 >= 0.0 && t2 <= 1.0))  //t1距离大于1nm，保存后精度有损失的bug
    return t1;

  return -1.0f;
}

qlib::Vec2d getRayIntersectionPoint(qlib::Vec2d& origin, qlib::Vec2d& vector, double distance) {
  qlib::Vec2d pt;

  pt.x = origin.x + vector.x * distance;
  pt.y = origin.y + vector.y * distance;

  return pt;
}

std::vector<qlib::Vec2d> getEntityBoundingBox(qlib::Cell::s_ptr current_cell, entt::entity el) {
  std::vector<qlib::Vec2d> m_obb;
  auto& reg = current_cell->reg;
  auto path = reg.try_get<qlib::Path::s_ptr>(el);
  auto polygon = reg.try_get<qlib::Polygon::s_ptr>(el);
  auto ellipse = reg.try_get<qlib::Ellipse::s_ptr>(el);
  auto rectangle = reg.try_get<qlib::Rectangle::s_ptr>(el);
  auto fan = reg.try_get<qlib::Fan::s_ptr>(el);
  auto ref = reg.try_get<qlib::Reference::s_ptr>(el);
  auto kp = reg.try_get<qlib::KeyPoint::s_ptr>(el);
  if (path)
    return (*path)->bounding_box();
  if (polygon)
    return (*polygon)->bounding_box();
  if (ellipse)
    return (*ellipse)->bounding_box();
  if (rectangle)
    return (*rectangle)->bounding_box();
  if (fan)
    return (*fan)->bounding_box();
  if (kp)
    return (*kp)->bounding_box();
  if (ref)
    return (*ref)->bounding_box();
  return m_obb;
}

std::vector<entt::entity> getIntersectNodes(layout::LayoutCmd& layout_cmd, qlib::Cell::s_ptr current_cell, qlib::Vec2d& ray_start,
                                            qlib::Vec2d& ray_dir, qlib::Vec2d& ray_dir_global, LayerRef::LayerModel& levelParam,
                                            std::vector<double> screen_box) {
  qlib::Vec2d min, max;
  if (levelParam.editing_ref_cell) {
    computeRayBoundingBox(transOutPoint(ray_start, levelParam), ray_dir_global, min, max, screen_box);
  } else {
    computeRayBoundingBox(ray_start, ray_dir, min, max, screen_box);
  }
  double w = std::max(max.x - min.x, 0.001);  //长宽为0的时候查询不出来
  double h = std::max(max.y - min.y, 0.001);
  std::vector<entt::entity>& nodes =
      getQueryEntities(layout_cmd.query_quad(min.x, min.y, w, h));  //LayoutCtrlData::getElementsByBox(min.x, min.y, w, h);  //包围盒所有相交
  std::vector<entt::entity> res;
  for (auto node : nodes) {
    std::vector<qlib::Vec2d> m_obb = getEntityBoundingBox(current_cell, node);
    if (m_obb.size() == 2 && rayIntersectsAABB2D(ray_start, ray_dir, m_obb[0], m_obb[1])) {
      res.push_back(node);
    }
  }
  return res;
}

bool isValidInsNode(entt::entity el) {
  // if (el == nullptr)
  //   return false;
  // if (el->getNodeMask() == NODE_NPICK)
  //   return false;
  // ElememtType t = el->getEleType();
  // if (t == ElememtType::LINE) {
  //   if (dynamic_cast<LineNode*>(el)->m_flexpath->m_elements[0].m_half_width_and_offset.x == 0) {
  //     return true;
  //   } else {
  //     return false;
  //   }
  // } else {
  //   return t == ElememtType::POLYGON || t == ElememtType::ELLIPSE || t == ElememtType::RECTANGLE ||
  //          t == ElememtType::REFERENCE || t == ElememtType::FAN;
  // }
  return true;
}

bool elementIsVisible(long layer_num) {
  // std::vector<std::string> info = LayoutCtrlData::getLayerStyleInfoOnNum(layer_num); //判断图层为隐藏状态
  // return info[6] == "unhide";
  return true;
}

void intersectWithPath(qlib::Path::s_ptr target_path, qlib::Path::s_ptr path, qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, int start_index,
                       int end_index, double& line_length, std::vector<qlib::Vec2d>& all_intersections, std::vector<int>& sel_indexs) {
  // if (!elementIsVisible(path->m_elements[0].m_layer))
  //   return;
  std::vector<qlib::Vec2d> points = path->spine.points;
  if (sel_indexs.empty()) {
    if (target_path == path) {
      //和自己对比
      for (size_t i = 0; i < points.size() - 1; ++i) {
        int s = i;
        int e = i + 1;
        //和除开相邻的线段对比
        if ((s >= end_index + 1) || (e <= start_index - 1)) {
          double dist = getRayToLineSegmentDist(ray_start, ray_dir, points[i], points[i + 1]);
          if (dist > 0 && dist > line_length) {
            qlib::Vec2d intersection = getRayIntersectionPoint(ray_start, ray_dir, dist);  //交点
            all_intersections.push_back(intersection);
          }
        }
      }
    } else {
      //和其他线对比
      for (size_t i = 0; i < points.size() - 1; ++i) {
        double dist = getRayToLineSegmentDist(ray_start, ray_dir, points[i], points[i + 1]);
        if (dist > 0 && dist > line_length) {
          qlib::Vec2d intersection = getRayIntersectionPoint(ray_start, ray_dir, dist);  //交点
          all_intersections.push_back(intersection);
        }
      }
    }

    //有宽度的线
    // if (target_path->m_elements[0].m_half_width_and_offset.x != 0) {
    //   std::vector<std::shared_ptr<GdsPolygon>> line_polygons = target_path->to_polygons();
    //   for (auto polygon : line_polygons) {
    //     intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, sel_indexs);
    //   }
    // }

    // if (path->m_elements[0].m_half_width_and_offset.x != 0) {
    //   std::vector<std::shared_ptr<GdsPolygon>> line_polygons = path->to_polygons();
    //   for (auto polygon : line_polygons) {
    //     intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, sel_indexs);
    //   }
    // }
  } else {
    //和部分求交
    int s = sel_indexs[0];
    int e = sel_indexs[1];
    if (target_path != path || (s >= end_index + 1) || (e <= start_index - 1)) {
      double dist = getRayToLineSegmentDist(ray_start, ray_dir, points[s], points[e]);
      if (dist > 0 && dist > line_length) {
        qlib::Vec2d intersection = getRayIntersectionPoint(ray_start, ray_dir, dist);  //交点
        all_intersections.push_back(intersection);
      }
    }
  }
}

void intersectWithPolygon(qlib::Polygon::s_ptr polygon, qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, double& line_length,
                          std::vector<qlib::Vec2d>& all_intersections, std::vector<int>& sel_indexs) {
  // if (!elementIsVisible(polygon->m_layer))
  //   return;
  std::vector<qlib::Vec2d> points = polygon->points;
  if (sel_indexs.empty()) {
    size_t numVertices = points.size();
    for (size_t i = 0; i < numVertices; ++i) {
      qlib::Vec2d& a = points[i];
      qlib::Vec2d& b = points[(i + 1) % numVertices];  // 循环取下一个点，实现闭合多边形
      double dist = getRayToLineSegmentDist(ray_start, ray_dir, a, b);
      if (dist > 0 && dist > line_length) {
        qlib::Vec2d intersection = getRayIntersectionPoint(ray_start, ray_dir, dist);  //交点
        all_intersections.push_back(intersection);
      }
    }
  } else {
    qlib::Vec2d& a = points[sel_indexs[0]];
    qlib::Vec2d& b = points[sel_indexs[1]];
    double dist = getRayToLineSegmentDist(ray_start, ray_dir, a, b);
    if (dist > 0 && dist > line_length) {
      qlib::Vec2d intersection = getRayIntersectionPoint(ray_start, ray_dir, dist);  //交点
      all_intersections.push_back(intersection);
    }
  }
}

void intersectWithRefer(qlib::Path::s_ptr target_path, qlib::Reference::s_ptr refer, qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, int start_index,
                        int end_index, double& line_length, std::vector<qlib::Vec2d>& all_intersections) {
  // std::vector<qlib::Path::s_ptr> refer_paths;        // = refer->get_paths(true, -1, false, 0);
  // std::vector<qlib::Polygon::s_ptr> refer_polygons;  // = refer->get_polygons(true, true, -1, false, 0);
  qlib::PathPtrArrayMap refer_paths;
  qlib::PolygonPtrArrayMap refer_polygons;
  refer->get_paths(true, -1, false, qlib::Tag{0, 0}, refer_paths);
  refer->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, refer_polygons);

  std::vector<int> empty;
  for (auto layer : refer_paths) {
    for (auto path : layer.second) {
      intersectWithPath(target_path, path, ray_start, ray_dir, start_index, end_index, line_length, all_intersections, empty);
    }
  }
  for (auto layer : refer_polygons) {
    for (auto polygon : layer.second) {
      intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, empty);
    }
  }
}

void intersectWithKeyPoint(qlib::Path::s_ptr target_path, qlib::KeyPoint::s_ptr kp, qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir, int start_index,
                           int end_index, double& line_length, std::vector<qlib::Vec2d>& all_intersections) {
  qlib::Vec2d targetPoint = kp->origin;
  qlib::Vec2d toPoint = targetPoint - ray_start;
  float epsilon = 1e-6f;
  // 1. 检查是否同方向（点积 >= 0）
  float dot = toPoint.x * ray_dir.x + toPoint.y * ray_dir.y;  //toPoint.dot(ray_dir);
  if (dot < -epsilon) {
    return;  // 方向相反
  }

  // 2. 检查是否共线（叉积 ≈ 0）
  if (abs(cross_product(toPoint, ray_dir)) > epsilon) {
    return;  // 不在同一直线上
  }

  // 3. 计算 t 值（t >= 0）
  float t;
  if (abs(ray_dir.x) > epsilon) {  // 避免除以0
    t = toPoint.x / ray_dir.x;
  } else if (abs(ray_dir.y) > epsilon) {
    t = toPoint.y / ray_dir.y;
  } else {
    return;  // 方向向量为0，无效
  }
  if (t >= -epsilon)  // t >= 0（考虑浮点误差）
    all_intersections.push_back(targetPoint);
}

qlib::Polygon::s_ptr getPolygon(qlib::Cell::s_ptr current_cell, entt::entity el_nod) {
  auto& reg = current_cell->reg;
  auto polygon = reg.try_get<qlib::Polygon::s_ptr>(el_nod);
  auto ellipse = reg.try_get<qlib::Ellipse::s_ptr>(el_nod);
  auto rectangle = reg.try_get<qlib::Rectangle::s_ptr>(el_nod);
  auto fan = reg.try_get<qlib::Fan::s_ptr>(el_nod);
  if (polygon) {
    return *polygon;
  }
  if (ellipse) {
    return (*ellipse)->to_polygon();
  }
  if (rectangle) {
    return (*rectangle)->to_polygon();
  }
  if (fan) {
    return (*fan)->to_polygon();
  }
  return nullptr;
}

void intersectWithAll(layout::LayoutCmd& layout_cmd, qlib::Cell::s_ptr current_cell, qlib::Path::s_ptr target_path, qlib::Vec2d& ray_start,
                      qlib::Vec2d& ray_dir, qlib::Vec2d& ray_dir_global, int& start_index, int& end_index, double& line_length,
                      std::vector<qlib::Vec2d>& all_intersections, LayerRef::LayerModel& levelParam, std::vector<double> screen_box) {
  std::vector<int> empty;
  std::vector<entt::entity> hits = getIntersectNodes(layout_cmd, current_cell, ray_start, ray_dir, ray_dir_global, levelParam,
                                                     screen_box);  //需要四叉树查询 屏幕包围盒剔除优化比对对象
  for (auto el_nod : hits) {
    if (!isValidInsNode(el_nod)) {
      continue;
    }
    auto& reg = current_cell->reg;
    auto line = reg.try_get<qlib::Path::s_ptr>(el_nod);
    auto refer = reg.try_get<qlib::Reference::s_ptr>(el_nod);
    auto kp = reg.try_get<qlib::KeyPoint::s_ptr>(el_nod);
    auto polygon = getPolygon(current_cell, el_nod);
    if (line) {
      intersectWithPath(target_path, *line, ray_start, ray_dir, start_index, end_index, line_length, all_intersections, empty);
    } else if (refer) {
      intersectWithRefer(target_path, *refer, ray_start, ray_dir, start_index, end_index, line_length, all_intersections);
    } else if (polygon) {
      // auto polygons = el_nod->getGdsPolygon();
      // for (auto polygon : polygons) {
      //   intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, empty);
      // }
      intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, empty);
    } else if (kp) {
      intersectWithKeyPoint(target_path, *kp, ray_start, ray_dir, start_index, end_index, line_length, all_intersections);
    }
  }
}

void intersectWithPickedElements(qlib::Cell::s_ptr current_cell, qlib::Path::s_ptr target_path, qlib::Vec2d& ray_start, qlib::Vec2d& ray_dir,
                                 int& start_index, int& end_index, double& line_length, std::vector<qlib::Vec2d>& all_intersections,
                                 std::vector<entt::entity>& overall_selected_nodes, std::vector<PartCheckedInfo>& part_selected_nodes) {
  std::vector<int> empty;
  auto& reg = current_cell->reg;
  //需要四叉树查询 屏幕包围盒剔除优化比对对象
  //与整体选择对象求交
  for (auto el_nod : overall_selected_nodes) {
    if (!isValidInsNode(el_nod)) {
      continue;
    }
    std::vector<qlib::Vec2d> m_obb = getEntityBoundingBox(current_cell, el_nod);
    if (m_obb.size() != 2 || !rayIntersectsAABB2D(ray_start, ray_dir, m_obb[0], m_obb[1]))
      continue;
    auto line = reg.try_get<qlib::Path::s_ptr>(el_nod);
    auto refer = reg.try_get<qlib::Reference::s_ptr>(el_nod);
    auto kp = reg.try_get<qlib::KeyPoint::s_ptr>(el_nod);
    auto polygon = getPolygon(current_cell, el_nod);
    if (line) {
      intersectWithPath(target_path, *line, ray_start, ray_dir, start_index, end_index, line_length, all_intersections, empty);
    } else if (refer) {
      intersectWithRefer(target_path, *refer, ray_start, ray_dir, start_index, end_index, line_length, all_intersections);
    } else if (polygon) {
      // auto polygons = el_nod->getGdsPolygon();
      // for (auto polygon : polygons) {
      //   intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, empty);
      // }
      intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, empty);
    } else if (kp) {
      intersectWithKeyPoint(target_path, *kp, ray_start, ray_dir, start_index, end_index, line_length, all_intersections);
    }
  }

  //与部分选择对象求交
  for (auto s_l : part_selected_nodes) {
    if (!isValidInsNode(s_l.node)) {
      continue;
    }
    std::vector<qlib::Vec2d> m_obb = getEntityBoundingBox(current_cell, s_l.node);
    if (m_obb.empty())
      continue;
    qlib::Vec2d min(m_obb[0].x, m_obb[0].y);
    qlib::Vec2d max(m_obb[1].x, m_obb[1].y);
    if (!rayIntersectsAABB2D(ray_start, ray_dir, min, max))
      continue;

    auto& reg = current_cell->reg;
    auto line = reg.try_get<qlib::Path::s_ptr>(s_l.node);
    if (line) {
      intersectWithPath(target_path, *line, ray_start, ray_dir, start_index, end_index, line_length, all_intersections, s_l.indexs);
    } else {
      auto ellipse = reg.try_get<qlib::Ellipse::s_ptr>(s_l.node);
      auto fan = reg.try_get<qlib::Fan::s_ptr>(s_l.node);
      auto polygon = getPolygon(current_cell, s_l.node);
      //对圆的部分选择做处理 提取边框求交
      if (ellipse) {
        std::vector<qlib::Vec2d> border_points = s_l.key_points;
        qlib::Polygon::s_ptr polygon_e = qlib::Polygon::create();
        polygon_e->layer = (*ellipse)->layer;
        polygon_e->points = border_points;
        intersectWithPolygon(polygon_e, ray_start, ray_dir, line_length, all_intersections, s_l.indexs);
      } else if (fan) {
        for (size_t i = 0; i < s_l.indexs.size() - 1; i++) {
          std::vector<int> line_indexs = {s_l.indexs[i], s_l.indexs[i + 1]};
          intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, line_indexs);
        }
      } else {
        // auto polygons = s_l.node->getGdsPolygon();
        // for (auto polygon : polygons) {
        //   intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, s_l.indexs);
        // }
        intersectWithPolygon(polygon, ray_start, ray_dir, line_length, all_intersections, s_l.indexs);
      }
    }
  }
}

bool elementIsSelected(qlib::Cell::s_ptr current_cell, qlib::Path::s_ptr target, std::vector<entt::entity>& overall_selected_nodes) {
  auto& reg = current_cell->reg;
  for (auto& node : overall_selected_nodes) {
    auto line = reg.try_get<qlib::Path::s_ptr>(node);
    if (line && target == *line) {
      return true;
    }
  }
  return false;
}

//执行最终延申线操作修改数据
void extendPath(qlib::Cell::s_ptr current_cell, entt::entity& path_entity, qlib::Path::s_ptr path_node, std::vector<ExtensionInfo>& extend_data,
                bool selected, undoRedoT::UndoRedoModule& undoRedoModule, layout::LayoutCmd& layout_cmd, ExtensionModel& param) {
  std::vector<qlib::Vec2d> origin_points = path_node->spine.points;  //要延伸的线
  std::vector<std::vector<qlib::Vec2d>> result_paths;
  std::vector<qlib::Vec2d> current_line_points;
  int max = origin_points.size() - 1;
  bool berfor_line_record = false;
  for (size_t i = 0; i < max; ++i) {
    int start = i;
    int end = i + 1;
    auto it = std::find_if(extend_data.begin(), extend_data.end(), [start](const ExtensionInfo& e) { return e.line_num == start; });
    //判定线段是否存在延长
    if (it != extend_data.end()) {
      //判定延长端在起点还是终点
      if (it->md_index == start) {
        if (start != 0 && !berfor_line_record) {
          result_paths.push_back(current_line_points);  //保存上一段线
        }
        current_line_points.clear();
        current_line_points.push_back(it->md_pos);
        current_line_points.push_back(origin_points[end]);
        berfor_line_record = false;
        if (end == max) {
          result_paths.push_back(current_line_points);
        }
      } else {
        current_line_points.push_back(origin_points[start]);
        current_line_points.push_back(it->md_pos);
        result_paths.push_back(current_line_points);
        current_line_points.clear();
        berfor_line_record = true;
      }
    } else {
      current_line_points.push_back(origin_points[start]);
      current_line_points.push_back(origin_points[end]);
      if (end == max) {
        result_paths.push_back(current_line_points);
      }
      berfor_line_record = false;
    }
  }

  if (result_paths.empty()) {
    result_paths.push_back(current_line_points);
  }

  //修改文件数据 添加新生成的线 删除原始的线
  auto& reg = current_cell->reg;
  // undoRedoModule.start(current_cell);
  for (auto path_points_array : result_paths) {
    qlib::Path::s_ptr path = qlib::Path::create();
    path->spine.points = filterDuplicatesPoints(path_points_array);
    path->layer = path_node->layer;
    // entt::entity entity = layout_cmd.add(path);
    param.adds.push_back(path);
    // undoRedoModule.add(entity);
    if (selected) {
      //自动选中
      // current_cell->reg.emplace_or_replace<select::SelectTag>(entity, select::SelectTag{}); //整体选中
      // param.selected.push_back(entity);
      param.selected.push_back(true);
    }
    param.selected.push_back(false);
  }
  param.removes.push_back(path_entity);
  // undoRedoModule.dele(path_entity);
  // layout_cmd.remove(path_entity);
}

void doExtendLine(layout::LayoutCmd& layout_cmd, entt::entity& path_entity, qlib::Path::s_ptr path_node,
                  std::vector<std::vector<int>>& picked_lines_index, std::vector<qlib::Vec2d>& hit_points, qlib::Cell::s_ptr current_cell,
                  std::vector<qlib::Vec2d>& extend_inters, std::vector<std::vector<qlib::Vec2d>>& extend_lines, bool& data_changed,
                  bool process_extend, LayerRef::LayerModel& levelParam, std::vector<entt::entity>& overall_selected_nodes,
                  std::vector<PartCheckedInfo>& part_selected_nodes, std::vector<double> screen_box, undoRedoT::UndoRedoModule undoRedoModule,
                  ExtensionModel& param) {
  // auto target_path = path_node->m_flexpath;
  std::vector<ExtensionInfo> extend_data;
  std::vector<qlib::Vec2d>& points = path_node->spine.points;
  int max = points.size() - 1;
  int i = 0;
  for (auto line_index : picked_lines_index) {
    std::vector<qlib::Vec2d> all_intersections;  //所有交点
    int start_index = line_index[0];             //延长线起点索引
    int end_index = line_index[1];               //延长线终点索引
    if (start_index >= max)
      continue;  //越界
    qlib::Vec2d start = points[start_index];
    qlib::Vec2d end = points[end_index];
    qlib::Vec2d ray_start = (start + end) / 2;  //中点
    qlib::Vec2d hit_point = hit_points[i];
    std::vector<qlib::Vec2d> line_points;  //线段顶点
    line_points.push_back(start);
    line_points.push_back(end);
    //   // bool f = false;
    qlib::Vec2d ray_end =
        distance(hit_point, start) < distance(hit_point, end) ? start : end;  //findNearestVertex(line_points, hit_point, f);    //射线端点
    int extend_index = ray_end == start ? start_index : end_index;            //要延伸端点的索引
    qlib::Vec2d ray_dir = normalizeVector(ray_end - ray_start);               //射线向量
    qlib::Vec2d ray_dir_global = ray_dir;                                     //射线全局向量
    bool isEditLowerLayer = levelParam.editing_ref_cell;                      //编辑下层
    if (isEditLowerLayer) {
      ray_dir_global = normalizeVector(transOutPoint(ray_end, levelParam) - transOutPoint(ray_start, levelParam));
    }
    //   //double line_length = std::sqrt(std::pow(ray_start.x - ray_end.x, 2) + std::pow(ray_start.y - ray_end.y, 2));  //线长
    double line_length = 0;  //线长
    bool inter_with_all = overall_selected_nodes.empty() && part_selected_nodes.empty();
    if (inter_with_all) {
      intersectWithAll(layout_cmd, current_cell, path_node, ray_end, ray_dir, ray_dir_global, start_index, end_index, line_length, all_intersections,
                       levelParam,
                       screen_box);  //与所有图形求延长交点
    } else {
      intersectWithPickedElements(current_cell, path_node, ray_end, ray_dir, start_index, end_index, line_length, all_intersections,
                                  overall_selected_nodes, part_selected_nodes);  //与选中的可交对象求交点
    }

    if (!all_intersections.empty()) {
      bool finded = false;
      qlib::Vec2d valid_inter = findNearestVertex(all_intersections, ray_end, finded);  //找到最近的交点
      if (!finded)
        continue;

      if (!inter_with_all || (inter_with_all && pointIsInsideScreen(valid_inter, levelParam, screen_box))) {
        extend_inters.push_back(valid_inter);
        std::vector<qlib::Vec2d> show_line;
        if (extend_index == start_index) {
          show_line.push_back(valid_inter);
          show_line.push_back(end);
        } else {
          show_line.push_back(start);
          show_line.push_back(valid_inter);
        }
        extend_lines.push_back(show_line);
        extend_data.push_back(ExtensionInfo(start_index, extend_index, valid_inter));
      }
    }
    i++;
  }

  if (process_extend && !extend_data.empty()) {
    bool selected = elementIsSelected(current_cell, path_node, overall_selected_nodes);
    extendPath(current_cell, path_entity, path_node, extend_data, selected, undoRedoModule, layout_cmd, param);  //执行延伸操作
    data_changed = true;
  }
}

void updateDisplayIntersAndLines(std::vector<qlib::Vec2d> points, std::vector<std::vector<qlib::Vec2d>> lines, qbe::layout::CellCmd& cmd,
                                 layout::CellState& cell_state) {
  // 渲染可视化辅助点和线
}

void clearExtensionDisplay(entt::entity& entity, qbe::layout::CellCmd& cmd, layout::CellState& cell_state) {
  if (entity != entt::null) {
    cmd.destroy_entity(entity, true);
    entity = entt::null;
    cell_state = layout::CellState::Render;
  }
}

//更新左下角信息 选中了要延申的线 是否存在交点
void updateExtensionStatusBarInfo(ecs::Bus& bus, bool picked_lines, bool no_inter_point, bool exist) {
  QString sendOperaterMessageInfo;
  if (!picked_lines) {
    sendOperaterMessageInfo =
        QObject::tr("Mode: Extend | Select the line segment to be extended and hold down the space bar to perform the trimming operation");
  } else {
    if (no_inter_point) {
      sendOperaterMessageInfo = QObject::tr("Mode:Extend | The current object cannot be extended");
    } else {
      sendOperaterMessageInfo = QObject::tr("Mode:Extend | The current object can be extended");
    }
  }
  if (exist) {
    sendOperaterMessageInfo = QObject::tr("");
  }
  bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{sendOperaterMessageInfo});
}

double distancePointToSegment(const qlib::Vec2d& Q, const qlib::Vec2d& P1, const qlib::Vec2d& P2) {
  // 线段的方向向量
  double dx = P2.x - P1.x;
  double dy = P2.y - P1.y;

  // 点 Q 到线段起点 P1 的向量
  double vx = Q.x - P1.x;
  double vy = Q.y - P1.y;

  // 计算线段长度的平方
  double segmentLengthSq = dx * dx + dy * dy;

  // 如果线段长度为 0，则点到线段起点的距离
  if (segmentLengthSq == 0) {
    return std::sqrt(vx * vx + vy * vy);
  }

  // 计算点到线段的投影比例 t
  double t = (vx * dx + vy * dy) / segmentLengthSq;

  // t 超出 [0, 1] 范围，点最近的点在线段端点之外
  if (t < 0) {
    return std::sqrt(vx * vx + vy * vy);
  } else if (t > 1) {
    double ex = Q.x - P2.x;
    double ey = Q.y - P2.y;
    return std::sqrt(ex * ex + ey * ey);
  }

  // 计算点到线段的最短距离
  double nearestX = P1.x + t * dx;
  double nearestY = P1.y + t * dy;
  double distance = std::sqrt((Q.x - nearestX) * (Q.x - nearestX) + (Q.y - nearestY) * (Q.y - nearestY));
  return distance;
}

std::vector<qlib::Vec2d> filterDuplicatesPoints(const std::vector<qlib::Vec2d>& points) {
  std::vector<qlib::Vec2d> result;

  if (points.empty()) {
    return result;  // 如果输入为空，直接返回空列表
  }
  // 添加第一个点
  result.push_back(points[0]);
  // 遍历剩余的点
  for (size_t i = 1; i < points.size(); ++i) {
    // 如果当前点与前一个点不相同，则添加到结果中
    if (!(points[i].x == points[i - 1].x && points[i].y == points[i - 1].y)) {
      result.push_back(points[i]);
    }
  }
  return result;
}
}  // namespace qbe::editing::Extension